package high.concurrent.pay.service.impl;

import com.alibaba.fastjson.JSONObject;
import high.concurrent.enums.BizCodeEnum;
import high.concurrent.exception.BizException;
import high.concurrent.pay.config.PayBeanConfig;
import high.concurrent.pay.config.WechatPayConfig;
import high.concurrent.pay.service.PayService;
import high.concurrent.utils.CommonUtil;
import high.concurrent.vo.PayInfoVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

/**
 * 微信支付实现类
 */
@Service
@Slf4j
public class WechatPayServiceImpl implements PayService {

    @Autowired
    private PayBeanConfig payBeanConfig;

    @Autowired
    private WechatPayConfig wechatPayConfig;

    @Autowired
    @Qualifier(value = "wechatPayClient")
    private CloseableHttpClient closeableHttpClient;

    /**
     * 统一下单
     * @param payInfoVO
     * @return
     */
    @Override
    public CloseableHttpResponse createOrder(PayInfoVO payInfoVO) {
        String outTradeNo = payInfoVO.getOutTradeNo();
        log.info("订单号 : {}", outTradeNo);
        // 支付参数配置
        JSONObject payObj = new JSONObject();
        payObj.put("appid", wechatPayConfig.getWxPayAppid());
        payObj.put("mchid", wechatPayConfig.getMchId());
        payObj.put("description", "测试商品");
        payObj.put("out_trade_no", outTradeNo);
        payObj.put("notify_url", wechatPayConfig.getCallbackUrl());

        // 金额json配置
        JSONObject amountObj = new JSONObject();
        // 支付金额：单位-分
        amountObj.put("total", payInfoVO.getPayFee());
        amountObj.put("currency", "CNY");

        payObj.put("amount", amountObj);

        // 附加参数配置(微信回调时会原封不动返回)
        String attachStr = "\"accountNo\":" + 888;
        payObj.put("attach", attachStr);

        String body = payObj.toJSONString();
        StringEntity stringEntity = new StringEntity(body, "utf-8");
        stringEntity.setContentType("application/json");

        HttpPost httpPost = new HttpPost(WechatPayConfig.Url.NATIVE_ORDER);
        httpPost.setHeader("Accept", "application/json");
        httpPost.setEntity(stringEntity);


        try(CloseableHttpResponse response = closeableHttpClient.execute(httpPost)) {
            // 响应码
            int statusCode = response.getStatusLine().getStatusCode();
            // 响应体
            String responseBody = EntityUtils.toString(response.getEntity());

            log.info("响应码: {}, 响应体: {}", statusCode, responseBody);
            return response;
        }catch (Exception e){
            log.error("下单异常");
            throw new BizException(BizCodeEnum.CREATE_DEFAIL);
        }
    }

    /**
     * 订单状态查询
     * @param payInfoVO
     * @return
     */
    @Override
    public CloseableHttpResponse selectOrderStatus(PayInfoVO payInfoVO) {
        String outTradeNo = payInfoVO.getOutTradeNo();
        String url = String.format(WechatPayConfig.Url.NATIVE_QUEUE, outTradeNo, wechatPayConfig.getMchId());
        log.info("url = {}", url);
        HttpGet httpGet = new HttpGet(url);
        httpGet.setHeader("Accept", "application/json");


        try(CloseableHttpResponse response = closeableHttpClient.execute(httpGet)) {
            // 响应码
            int statusCode = response.getStatusLine().getStatusCode();
            // 响应体
            String responseBody = EntityUtils.toString(response.getEntity());

            log.info("响应码: {}, 响应体: {}", statusCode, responseBody);
            return response;
        }catch (Exception e){
            log.error("下单异常");
            throw new BizException(BizCodeEnum.QUEUE_DEFAIL);
        }
    }

    /**
     * 关闭订单
     * @param payInfoVO
     * @return
     */
    @Override
    public CloseableHttpResponse closeOrder(PayInfoVO payInfoVO) {
        String outTradeNo = payInfoVO.getOutTradeNo();

        JSONObject payCloseObj = new JSONObject();
        payCloseObj.put("mchid", wechatPayConfig.getMchId());

        String body = payCloseObj.toJSONString();
        StringEntity stringEntity = new StringEntity(body, "utf-8");
        stringEntity.setContentType("application/json");

        String url = String.format(WechatPayConfig.Url.NATIVE_CLOSE, outTradeNo);
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("Accept", "application/json");
        httpPost.setEntity(stringEntity);


        try(CloseableHttpResponse response = closeableHttpClient.execute(httpPost)) {
            // 响应码
            int statusCode = response.getStatusLine().getStatusCode();
            log.info("响应码: {}, 无响应体", statusCode);
            return response;
        }catch (Exception e){
            log.error("下单异常");
            throw new BizException(BizCodeEnum.CLOSE_DEFAIL);
        }
    }

    /**
     * 退款
     * @param payInfoVO
     * @return
     */
    @Override
    public CloseableHttpResponse refundOrder(PayInfoVO payInfoVO) {
        // 订单号
        String outTradeNo = payInfoVO.getOutTradeNo();
        // 退款订单号（0030720233465776714273860677611443852205648507821776306055453447）
        String outRefundNo = payInfoVO.getOutRefundNo();
        log.info("退款订单号: {}", outRefundNo);

        JSONObject refundObj = new JSONObject();
        refundObj.put("out_trade_no", outTradeNo);
        refundObj.put("out_refund_no", outRefundNo);

        JSONObject amountObj = new JSONObject();
        // 退款的金额，单位：分
        amountObj.put("refund", payInfoVO.getRefundAmount());
        // 原订单支付金额: 单位分
        amountObj.put("total", payInfoVO.getPayFee());
        amountObj.put("currency", "CNY");

        refundObj.put("amount", amountObj);

        String body = refundObj.toJSONString();
        StringEntity stringEntity = new StringEntity(body, "utf-8");
        stringEntity.setContentType("application/json");

        HttpPost httpPost = new HttpPost(WechatPayConfig.Url.NATIVE_REFUND);
        httpPost.setHeader("Accept", "application/json");
        httpPost.setEntity(stringEntity);


        try(CloseableHttpResponse response = closeableHttpClient.execute(httpPost)) {
            // 响应码
            int statusCode = response.getStatusLine().getStatusCode();
            // 响应体
            String responseBody = EntityUtils.toString(response.getEntity());

            log.info("响应码: {}, 响应体: {}", statusCode, responseBody);
            return response;
        }catch (Exception e){
            log.error("下单异常");
            throw new BizException(BizCodeEnum.REFUND_DEFAIL);
        }
    }

    /**
     * 退款状态查询
     * @param payInfoVO
     * @return
     */
    @Override
    public CloseableHttpResponse selectRefundOrderStatus(PayInfoVO payInfoVO) {
        String outRefundNo = payInfoVO.getOutRefundNo();
        String url = String.format(WechatPayConfig.Url.NATIVE_QUEUE_REFUND, outRefundNo);
        log.info("url = {}", url);
        HttpGet httpGet = new HttpGet(url);
        httpGet.setHeader("Accept", "application/json");


        try(CloseableHttpResponse response = closeableHttpClient.execute(httpGet)) {
            // 响应码
            int statusCode = response.getStatusLine().getStatusCode();
            // 响应体
            String responseBody = EntityUtils.toString(response.getEntity());

            log.info("响应码: {}, 响应体: {}", statusCode, responseBody);
            return response;
        }catch (Exception e){
            log.error("下单异常");
            throw new BizException(BizCodeEnum.REFUND_QUEUE_DEFAIL);
        }
    }
}
